#pragma once
#include <iostream>
#include <functional>
#include <sys/epoll.h>

class Epoller;
class EventLoop;

class Channel
{
private:
    int _fd;
    EventLoop *_loop;
    uint32_t _events;  // 当前需要监控的事件
    uint32_t _revents; // 当前连续触发的事件
    using EventCallback = std::function<void()>;
    EventCallback _read_callback;  // 可读事件被触发的回调函数
    EventCallback _write_callback; // 可写事件被触发的回调函数
    EventCallback _error_callback; // 错误事件被触发的回调函数
    EventCallback _close_callback; // 连接断开事件被触发的回调函数
    EventCallback _event_callback; // 任意事件被触发的回调函数
public:
    Channel(int fd, EventLoop *loop) : _fd(fd), _events(0), _revents(0), _loop(loop)
    {
    }
    int Fd() { return _fd; }
    void SetReadCallBack(const EventCallback &cb) { _read_callback = cb; }
    void SetWriteCallBack(const EventCallback &cb) { _write_callback = cb; }
    void SetErrorCallBack(const EventCallback &cb) { _error_callback = cb; }
    void SetCloseCallBack(const EventCallback &cb) { _close_callback = cb; }
    void SetEventCallBack(const EventCallback &cb) { _event_callback = cb; }

    // 添加就绪事件
    void SetRevents(uint32_t events) { _revents = events; }
    // 获取想要监控的事件
    uint32_t GetRevents() { return _events; }
    // 当前是否监控可读
    bool ReadAble() { return (_events & EPOLLIN); }
    // 当前是否监控可写
    bool WriteAble() { return (_events & EPOLLOUT); }
    // 启动读事件监控
    void EnableRead()
    {
        _events |= EPOLLIN;
        Update();
    }
    // 启动写事件监控
    void EnableWrite()
    {
        _events |= EPOLLOUT;
        Update();
    }
    // 关闭读事件监控
    void DisableRead()
    {
        _events &= ~EPOLLIN;
        Update();
    }
    // 关闭写事件监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT;
        Update();
    }
    // 关闭所有事件监控
    void DisableAll()
    {
        _events = 0;
        Update();
    }
    // 移除监控
    void Remove();
    // 更新监控事件
    void Update();
    // 事件处理
    void HandleEvent()
    {
        // 读事件就绪 或者 对方把连接关闭了
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if (_read_callback)
                _read_callback();
        }
        if (_revents & EPOLLOUT)
        {
            if (_write_callback)
                _write_callback();
        }
        if (_revents & EPOLLERR)
        {
            if (_error_callback)
                _error_callback();
        }
        if (_revents & EPOLLHUP)
        {
            if (_close_callback)
                _close_callback();
        }

        if (_event_callback)
            _event_callback();
    }
};